﻿using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using TianYu.Core.Common.NPOI;
using System.Data;
using TianYu.Core.Common;

namespace System
{
    public static class NPOIExtension
    {
        public static List<TableParams> ArrayToTableParams(this string[] @this)
        {
            List<TableParams> tableParams = new List<TableParams>();
            foreach (var item in @this)
            {
                tableParams.Add(new TableParams(item));
            }

            return tableParams;
        }

        public static List<SheetModel> DicToTableParams(this Dictionary<string, DataTable> @this, Dictionary<string, string[]> tableHeader)
        {
            var sheetList = new List<SheetModel>();

            foreach (var item in tableHeader)
            {
                var tableParamsList = new List<TableParams>();

                foreach (var m in item.Value)
                {
                    tableParamsList.Add(new TableParams(m));
                }

                if (@this == null) continue;

                sheetList.Add(new SheetModel
                {
                    SheetName = item.Key,
                    TableParamsList = tableParamsList,
                    Data = @this[item.Key]
                });
            }

            return sheetList;
        }

        public static List<PicturesInfo> GetAllPictureInfos(this ISheet sheet)
        {
            return sheet.GetAllPictureInfos(null, null, null, null);
        }

        public static List<PicturesInfo> GetAllPictureInfos(this ISheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol, bool onlyInternal = true)
        {
            if (sheet is HSSFSheet)
            {
                return GetAllPictureInfos((HSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            else if (sheet is XSSFSheet)
            {
                return GetAllPictureInfos((XSSFSheet)sheet, minRow, maxRow, minCol, maxCol, onlyInternal);
            }
            else
            {
                throw new Exception("未处理类型，没有为该类型添加：GetAllPicturesInfos()扩展方法！");
            }
        }
        /// <summary>
        /// 获取图片和位置 (xls)
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <returns></returns>
        private static List<PicturesInfo> GetAllPictureInfos(HSSFSheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol, bool onlyInternal)
        {
            List<PicturesInfo> picturesInfoList = new List<PicturesInfo>();

            var shapeContainer = sheet.DrawingPatriarch as HSSFShapeContainer;
            if (null != shapeContainer)
            {
                var shapeList = shapeContainer.Children;
                foreach (var shape in shapeList)
                {
                    if (shape is HSSFPicture && shape.Anchor is HSSFClientAnchor)
                    {
                        var picture = (HSSFPicture)shape;
                        var anchor = (HSSFClientAnchor)shape.Anchor;

                        if (IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, onlyInternal))
                        {
                            picturesInfoList.Add(new PicturesInfo(anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, picture.PictureData.Data, picture.PictureData.PictureType));
                        }
                    }
                }
            }

            return picturesInfoList;
        }
        /// <summary>
        /// 获取图片和位置 (xlsx)
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="minRow"></param>
        /// <param name="maxRow"></param>
        /// <param name="minCol"></param>
        /// <param name="maxCol"></param>
        /// <param name="onlyInternal"></param>
        /// <returns></returns>
        private static List<PicturesInfo> GetAllPictureInfos(XSSFSheet sheet, int? minRow, int? maxRow, int? minCol, int? maxCol, bool onlyInternal)
        {
            List<PicturesInfo> picturesInfoList = new List<PicturesInfo>();

            var documentPartList = sheet.GetRelations();
            foreach (var documentPart in documentPartList)
            {
                if (documentPart is XSSFDrawing)
                {
                    var drawing = (XSSFDrawing)documentPart;
                    var shapeList = drawing.GetShapes();
                    foreach (var shape in shapeList)
                    {
                        if (shape is XSSFPicture)
                        {
                            var picture = (XSSFPicture)shape;
                            IClientAnchor anchor;
                            try
                            {
                                anchor = picture.GetPreferredSize();
                            }
                            catch (NullReferenceException)
                            {
                                throw new TYBaseException("插入图片方式错误：请将图片设置嵌入单元格再切换为浮动图片");
                            }
                            if (IsInternalOrIntersect(minRow, maxRow, minCol, maxCol, anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, onlyInternal))
                            {
                                picturesInfoList.Add(new PicturesInfo(anchor.Row1, anchor.Row2, anchor.Col1, anchor.Col2, picture.PictureData.Data, picture.PictureData.PictureType));
                            }
                        }
                    }
                }
            }
            return picturesInfoList;
        }

        private static bool IsInternalOrIntersect(int? rangeMinRow, int? rangeMaxRow, int? rangeMinCol, int? rangeMaxCol,
            int pictureMinRow, int pictureMaxRow, int pictureMinCol, int pictureMaxCol, bool onlyInternal)
        {
            int _rangeMinRow = rangeMinRow ?? pictureMinRow;
            int _rangeMaxRow = rangeMaxRow ?? pictureMaxRow;
            int _rangeMinCol = rangeMinCol ?? pictureMinCol;
            int _rangeMaxCol = rangeMaxCol ?? pictureMaxCol;

            if (onlyInternal)
            {
                return (_rangeMinRow <= pictureMinRow && _rangeMaxRow >= pictureMaxRow &&
                        _rangeMinCol <= pictureMinCol && _rangeMaxCol >= pictureMaxCol);
            }
            else
            {
                return ((Math.Abs(_rangeMaxRow - _rangeMinRow) + Math.Abs(pictureMaxRow - pictureMinRow) >= Math.Abs(_rangeMaxRow + _rangeMinRow - pictureMaxRow - pictureMinRow)) &&
                (Math.Abs(_rangeMaxCol - _rangeMinCol) + Math.Abs(pictureMaxCol - pictureMinCol) >= Math.Abs(_rangeMaxCol + _rangeMinCol - pictureMaxCol - pictureMinCol)));
            }
        }

        /// <summary>根据单元格类型获取单元格的数据</summary>
        public static object GetValue(this ICell @this)
        {
            if (@this == null) return null;

            switch (@this.CellType)
            {
                case CellType.Blank: //BLANK:
                    return null;
                case CellType.Boolean: //BOOLEAN:
                    return @this.BooleanCellValue;
                case CellType.Numeric: //NUMERIC:
                    return @this.NumericCellValue;
                case CellType.String: //STRING:
                    return @this.StringCellValue;
                case CellType.Error: //ERROR:
                    return @this.ErrorCellValue;
                case CellType.Formula: //FORMULA:
                    switch (@this.CachedFormulaResultType)
                    {
                        case CellType.Boolean:
                            return @this.BooleanCellValue;
                        case CellType.Error:
                            return @this.ErrorCellValue;
                        case CellType.Numeric:
                            return @this.NumericCellValue;
                        case CellType.String:
                            return @this.StringCellValue;
                        default:
                            return string.Empty;
                    }
                default:
                    return string.Empty;
            }
        }

        /// <summary>
        /// 获取单元格跨度
        /// </summary>
        /// <param name="sheet"></param>
        /// <param name="rowIndex"></param>
        /// <param name="colIndex"></param>
        /// <param name="regionsCount"></param> 
        public static (short rowSpan, short colSpan) GetMergedRegion(this ISheet sheet, int rowIndex, int colIndex)
        {
            short rowSpan = 1;
            short colSpan = 1;
            int regionsCount = sheet.NumMergedRegions;
            for (int i = 0; i < regionsCount; i++)
            {
                var range = sheet.GetMergedRegion(i);
                if (range.FirstRow == rowIndex && range.FirstColumn == colIndex)
                {
                    rowSpan = (short)(range.LastRow - range.FirstRow + 1);
                    colSpan = (short)(range.LastColumn - range.FirstColumn + 1);
                    break;
                }
            }
            return (rowSpan, colSpan);
        }

        public static string GetExtendName(this PictureType @this)
        {
            var extend = new string[] { "", "", ".emf", ".wmf", ".pict", ".jpeg", ".png", ".dib", ".gif", ".tiff", ".eps", ".bmp", ".wpg" };

            return extend[(int)@this];
        }
    }
}
